package net.sudot.chess.business.controller.web;

import me.chanjar.weixin.common.bean.WxJsapiSignature;
import net.sudot.chess.business.controller.AbstractBaseController;
import net.sudot.chess.business.dto.CustomerDetailDTO;
import net.sudot.chess.business.dto.DateTimeScopeDTO;
import net.sudot.chess.business.model.Customer;
import net.sudot.chess.business.service.InviteRecordService;
import net.sudot.chess.business.wechat.api.WechatApiService;
import net.sudot.chess.config.Cycle;
import net.sudot.chess.config.SystemProperties;
import net.sudot.chess.util.QrcodeUtils;
import net.sudot.commons.security.LoginUser;
import net.sudot.commons.utils.ResponseMessage;
import net.sudot.commons.utils.WebUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Controller;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URL;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 邀请好友
 *
 * @author tangjialin on 2018-03-25.
 */
@Controller
@RequestMapping(value = "/invite")
public class InviteController extends AbstractBaseController {
    @Resource
    private SystemProperties systemProperties;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private WechatApiService wechatApiService;
    @Resource
    private InviteRecordService inviteRecordService;

    /**
     * 邀请好友视图
     *
     * @return 返回邀请好友视图
     */
    @GetMapping("/index")
    public String index(@LoginUser Customer customer, HttpServletRequest request) {
        Long inviter = customer.getId();
        String website = systemProperties.getWebsite();
        String inviteLink = website + "/qrcode/invite/" + inviter;
        try {
            String requestURI = WebUtils.getRequestFullUrl(website, request);
            WxJsapiSignature signature = wechatApiService.createJsapiSignature(requestURI);
            request.setAttribute("signature", signature);
        } catch (Exception e) {
            logger.warn("微信JSSDK前面生成失败", e);
        }
        request.setAttribute("inviteLink", inviteLink);
        request.setAttribute("invitePic", website + "/static/images/logo.jpg");
        return "invite/index";
    }

    /**
     * 邀请的好友列表视图
     *
     * @return 返回邀请的好友列表视图
     */
    @GetMapping("/list")
    public String list() {
        return "invite/list";
    }

    /**
     * 返回邀请者信息
     *
     * @param customer
     * @return
     */
    @PostMapping("/inviter")
    @ResponseBody
    public CustomerDetailDTO inviter(@LoginUser Customer customer) {
        CustomerDetailDTO detailDTO = new CustomerDetailDTO();
        Customer inviter = inviteRecordService.findByInvitee(customer.getId());
        if (inviter != null) {
            detailDTO.setId(inviter.getId())
                    .setNickname(inviter.getNickname())
                    .setHead(inviter.getHead());
        }
        return detailDTO;
    }

    /**
     * 返回邀请者信息
     *
     * @param customer         登录客户信息
     * @param dateTimeScopeDTO 时间范围
     *                         start    起始时间
     *                         end      结束时间
     * @return 返回用户的邀请人信息
     */
    @PostMapping("/list")
    @ResponseBody
    public List<CustomerDetailDTO> list(@LoginUser Customer customer, @RequestBody(required = false) DateTimeScopeDTO dateTimeScopeDTO) {
        Instant start = dateTimeScopeDTO == null ? null : dateTimeScopeDTO.getStart();
        Instant end = dateTimeScopeDTO == null ? null : dateTimeScopeDTO.getEnd();
        Cycle cycle = systemProperties.getBrokerageCycle();
        if (start == null || end == null || Duration.between(start, end).toDays() > (cycle.getDuration() * cycle.getUnit().value().getDuration().toDays())) {
            Cycle.CycleCalc cycleCalc = new Cycle.CycleCalc(LocalDate.now(), cycle);
            start = cycleCalc.getStartDateWidth();
            end = cycleCalc.getEndDateWidth();
        }
        return inviteRecordService.findListByInviter(customer.getId(), start, end);
    }

    /**
     * 生成二维码
     *
     * @param customer 登录客户信息
     * @param request  HttpServletRequest
     * @return 返回生成的二维码Base64编码格式数据
     */
    @PostMapping("/qrcode")
    @ResponseBody
    public ResponseMessage qrcode(@LoginUser Customer customer, HttpServletRequest request) {
        ResponseMessage responseMessage = new ResponseMessage();
        Long inviter = customer.getId();
        // http://www.xxx.com/qrcode/invite/inviter
        String content = systemProperties.getWebsite() + "/qrcode/invite/" + inviter;
        ValueOperations<String, Object> opsForValue = redisTemplate.opsForValue();
        String key = "qrcode:invite:" + inviter;
        Object qrCodeBase64 = opsForValue.get(key);
        if (qrCodeBase64 != null) {
            return responseMessage.setSuccess(true).setData(qrCodeBase64);
        }
        InputStream logo = null;
        String head = customer.getHead();
        if (head != null && !head.isEmpty()) {
            try {
                // 用户头像
                byte[] bytes = IOUtils.toByteArray(new URL(head));
                logo = new ByteArrayInputStream(bytes);
            } catch (Exception e) {
                logo = null;
                logger.error("用户头像获取失败:{}", head, e);
            }
        }
        try {
            // 生成二维码
            byte[] qrCode = QrcodeUtils.createQrcode(content, logo);
            qrCodeBase64 = Base64Utils.encodeToString(qrCode);
            opsForValue.set(key, qrCodeBase64, 3, TimeUnit.HOURS);
        } catch (Exception e) {
            logger.error("用户二维码生成失败", e);
        }
        return responseMessage.setSuccess(qrCodeBase64 != null).setData(qrCodeBase64);
    }

    /**
     * 好友历史充值时间表
     *
     * @return 返回时间表视图
     */
    @GetMapping("/history")
    public String history() {
        return "invite/history";
    }

    /**
     * 好友历史充值时间表
     *
     * @return 返回时间表视图
     */
    @GetMapping("/history/schedule")
    @ResponseBody
    public DateTimeScopeDTO schedule(@LoginUser Customer customer) {
        Instant now = Instant.now();
        Instant minInstant = customer.getCreatedDate();
        Cycle cycle = systemProperties.getBrokerageCycle();
        Cycle.CycleCalc cycleCalc = new Cycle.CycleCalc(now.atZone(ZoneId.systemDefault()).toLocalDate(), cycle);
        Instant start = cycleCalc.getStartDateWidth();
        Instant end = cycleCalc.getEndDateWidth();
        int days = (int) (cycle.getDuration() * cycle.getUnit().value().getDuration().toDays());
        return new DateTimeScopeDTO().setStart(start).setEnd(end).setDuration(days).setMin(minInstant);
    }

}
